package com.goods.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.goods.business.entities.*;
import com.goods.business.mapper.*;
import com.goods.business.service.OutStockService;
import com.goods.common.error.BusinessCodeEnum;
import com.goods.common.error.BusinessException;
import com.goods.common.vo.business.ConsumerVO;
import com.goods.common.vo.business.OutStockItemVO;
import com.goods.common.vo.business.OutStockVO;
import com.goods.common.vo.system.PageVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Decheng Kong
 * @date 2021/11/9 20:50
 */
@Service
public class OutStockServiceImpl implements OutStockService {

    @Autowired
    private OutStockMapper outStockMapper;

    @Autowired
    private OutStockInfoMapper outStockInfoMapper;
    @Autowired
    private ConsumerMapper consumerMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductStockMapper productStockMapper;


    @Override
    public PageVO<OutStockVO> findOutStockList(Integer pageNum, Integer pageSize, OutStockVO outStockVO) {

        PageHelper.startPage(pageNum, pageSize);

        Example example = new Example(OutStock.class);
        Example.Criteria criteria = example.createCriteria();

        if (outStockVO.getStatus() != null) {
            criteria.andEqualTo("status", outStockVO.getStatus());
        }

        if (outStockVO.getType() != null) {
            criteria.andEqualTo("type", outStockVO.getType());
        }

        if (!StringUtils.isEmpty(outStockVO.getOutNum())) {
            criteria.andEqualTo("outNum", outStockVO.getOutNum());
        }


        List<OutStock> outStocks = outStockMapper.selectByExample(example);
        List<OutStockVO> collect = outStocks.stream().map(outStock -> {
            OutStockVO outStockVO1 = new OutStockVO();
            BeanUtils.copyProperties(outStock, outStockVO1);
            Consumer consumer = consumerMapper.selectByPrimaryKey(outStock.getConsumerId());
            BeanUtils.copyProperties(consumer, outStockVO1, "id", "createTime", "modifiedTime");

            return outStockVO1;

        }).collect(Collectors.toList());

        PageInfo<OutStock> info = new PageInfo<>(outStocks);
        return new PageVO<>(info.getTotal(), collect);
    }

    @Override
    public Map<String, Object> findInStockDetailList(Integer pageNum, Integer pageSize, Integer id) {

        OutStock outStock = outStockMapper.selectByPrimaryKey(id);

        // 查询供应商信息
        Long consumerId = outStock.getConsumerId();
        Consumer consumer = consumerMapper.selectByPrimaryKey(consumerId);
        ConsumerVO consumerVO = new ConsumerVO();
        BeanUtils.copyProperties(consumer, consumerVO);

        // 查询商品信息
        String outNum = outStock.getOutNum();

        PageHelper.startPage(pageNum, pageSize);
        Example example = new Example(OutStockInfo.class);
        example.createCriteria().andEqualTo("outNum", outNum);
        List<OutStockInfo> outStockInfos = outStockInfoMapper.selectByExample(example);
        List<OutStockItemVO> collect = outStockInfos.stream().map(inStockInfo -> {
            // 查询商品
            Example example1 = new Example(Product.class);
            example1.createCriteria().andEqualTo("pNum", inStockInfo.getpNum());
            Product product = productMapper.selectOneByExample(example1);
            // safe code
            if (Objects.isNull(product)) {
                product = new Product();
            }
            // 转VO
            OutStockItemVO outStockItemVO = new OutStockItemVO();
            BeanUtils.copyProperties(product, outStockItemVO);
            // 设置数量
            outStockItemVO.setCount(inStockInfo.getProductNumber());
            return outStockItemVO;

        }).collect(Collectors.toList());
        // 商品的分页信息
        PageInfo<OutStockInfo> info = new PageInfo<>(outStockInfos);
        Map<String, Object> res = new HashMap<>();
        res.put("total", info.getTotal());
        res.put("itemVOS", collect);
        res.put("consumerVO", consumerVO);
        res.put("status", outStock.getStatus());
        return res;
    }

    @Override
    public void updateOutStockStatus(Long id, int code) {
        OutStock outStock = new OutStock();
        outStock.setId(id);
        outStock.setStatus(code);
        outStockMapper.updateByPrimaryKeySelective(outStock);
    }

    @Override
    public void deleteOutStockById(Long id) {
        // 删除出库单明细
        OutStock outStock = outStockMapper.selectByPrimaryKey(id);
        String outNum = outStock.getOutNum();
        Example example = new Example(OutStockInfo.class);
        example.createCriteria().andEqualTo("outNum", outNum);
        outStockMapper.deleteByExample(example);

        // 删除入库单
        outStockMapper.deleteByPrimaryKey(id);
    }

    @Override
    public void addOutStock(OutStockVO outStockVO) {
        // 创建时间
        Date createDate = new Date();
        // 出库清单
        List<Object> products = outStockVO.getProducts();

        if (outStockVO.getConsumerId() == null) {
            // 新增去向
            long consumerId = insertConsumer(outStockVO, createDate);
            outStockVO.setConsumerId(consumerId);
        }

        // 已知去向
        // 新增出库单
        String outNum = insertOutStock(outStockVO, createDate, products, outStockVO.getConsumerId());
        // TODO 事务不生效
        // test transition
        // if (inNum != null) {
        //     throw new BusinessException(BusinessCodeEnum.PRODUCT_IN_STOCK_NUMBER_ERROR);
        // }
        // 新增入库清单
        insertOutStockInfo(createDate, products, outNum);
    }

    @Override
    public void auditOutStock(Long id, int code) throws BusinessException {
        OutStock outStock = outStockMapper.selectByPrimaryKey(id);
        String outNum = outStock.getOutNum();
        Example example = new Example(OutStockInfo.class);
        example.createCriteria().andEqualTo("outNum", outNum);
        List<OutStockInfo> outStockInfos = outStockInfoMapper.selectByExample(example);


        for (OutStockInfo outStockInfo : outStockInfos) {
            Example example1 = new Example(ProductStock.class);
            example1.createCriteria().andEqualTo("pNum", outStockInfo.getpNum());
            ProductStock productStock = productStockMapper.selectOneByExample(example1);

            if (productStock == null) {
                // 物资不存在
                throw new BusinessException(BusinessCodeEnum.PRODUCT_NOT_FOUND);
            }

            // 更新物资库存数量
            long balance = productStock.getStock() - outStockInfo.getProductNumber();

            if (balance < 0) {
                // 库存不足
                throw new BusinessException(BusinessCodeEnum.PRODUCT_STOCK_ERROR);
            }
            productStock.setStock(balance);
            productStockMapper.updateByPrimaryKey(productStock);
        }

        // 更新状态
        updateOutStockStatus(id, code);
    }

    private void insertOutStockInfo(Date createDate, List<Object> products, String outNum) {
        products.forEach(object -> {

            String s = JSON.toJSONString(object);
            JSONObject jsonObject = JSONObject.parseObject(s);

            Product product = productMapper.selectByPrimaryKey(jsonObject.get("productId"));
            OutStockInfo outStockInfo = new OutStockInfo();
            outStockInfo.setOutNum(outNum);
            outStockInfo.setpNum(product.getPNum());
            outStockInfo.setProductNumber((Integer) jsonObject.get("productNumber"));
            outStockInfo.setCreateTime(createDate);
            outStockInfo.setModifiedTime(createDate);
            outStockInfoMapper.insert(outStockInfo);
        });
    }

    private String insertOutStock(OutStockVO outStockVO, Date createDate, List<Object> products, Long consumerId) {

        OutStock outStock = new OutStock();
        BeanUtils.copyProperties(outStockVO, outStock);
        outStock.setOutNum(UUID.randomUUID().toString().replace("-", ""));
        outStock.setOperator("admin");
        outStock.setCreateTime(createDate);
        outStock.setProductNumber(products.size());
        outStock.setConsumerId(consumerId);
        outStock.setStatus(2);
        outStockMapper.insert(outStock);

        return outStock.getOutNum();
    }

    private long insertConsumer(OutStockVO outStockVO, Date createDate) {
        Consumer consumer = new Consumer();
        BeanUtils.copyProperties(outStockVO, consumer);
        consumer.setCreateTime(createDate);
        consumer.setModifiedTime(createDate);

        consumerMapper.insertSelective(consumer);
        // 主键回显
        return consumer.getId();
    }
}
